package org.example.comp_algorithm_back.algorithm;

import org.example.comp_algorithm_back.domain.CompWord;
import org.example.comp_algorithm_back.util.DataFormatUtil;
import org.example.comp_algorithm_back.vo.WordSearchVo;

import java.util.*;
import java.io.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class CompSurvey {

    private static final Map<String, Double> surveyScores = new HashMap<>();

    public static void compSurvey(WordSearchVo vo, String filePath, double wCompkey, double wSurvey) {
        ArrayList<double[]> data = readData(filePath);
        ArrayList<CompWord> keywords = vo.getKeywords();
        if (data == null || data.isEmpty()) {

            System.out.println("Failed to read data from file.");
            return;
        }

        if(data.get(0).length != keywords.size()) {
            System.out.println("Wrong number of words.");
            return;
        }
        vo.setFlag(true);

        for (int i = 0; i < keywords.size(); i++) {
            double[] scores = new double[data.size()];
            for (int j = 0; j < data.size(); j++) {
                scores[j] = data.get(j)[i];
            }

            // 平均值
            double mean = calculateMean(scores);
            // 方差
            double stdDev = calculateStandardDeviation(scores, mean);
            surveyScores.put(keywords.get(i).getMidWord(), mean);
            vo.getMeans().add(mean);
            vo.getStdDevs().add(DataFormatUtil.roundToFourDecimalPlaces(stdDev));
        }

        int n = 3;
        //平均值最大的前n个
        List<Integer> strong = findTopNIndices(vo.getMeans(), n, Comparator.reverseOrder());
        //平均值最小的前n个
        List<Integer> weak = findTopNIndices(vo.getMeans(), n, Comparator.naturalOrder());
        //方差最大的前n个
        List<Integer> diff = findTopNIndices(vo.getStdDevs(), n, Comparator.reverseOrder());
        for(int i = 0; i < n; i++){
            int index1 = strong.get(i);
            int index2 = weak.get(i);
            int index3 = diff.get(i);
            if(vo.getMeans().get(index1) >= 3){
//                String res = keywords.get(index1).getMidWord() + "/" + keywords.get(index1).getWord();
                vo.getStrong().add(index1);
            }

            if(vo.getMeans().get(index2) < 3){
//                String res = keywords.get(index2).getMidWord() + "/" + keywords.get(index2).getWord();
                vo.getWeak().add(index2);
            }

            if(vo.getStdDevs().get(index3) > 0){
//                String res = keywords.get(index3).getMidWord() + "/" + keywords.get(index3).getWord();
                vo.getDiff().add(index3);
            }
        }

        List<Map.Entry<String, Double>> rankedKeywords = rankKeywords(keywords, wSurvey, wCompkey);

        // 打印排序后的结果
        for (Map.Entry<String, Double> entry : rankedKeywords) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }

        vo.setRankedKeywords(rankedKeywords);

    }

    private static ArrayList<double[]> readData(String filePath) {
        ArrayList<double[]> data = new ArrayList<>();

        try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = br.readLine()) != null) {
                String[] parts = line.split(" ");
                double[] row = new double[parts.length];
                for (int i = 0; i < parts.length; i++) {
                    row[i] = Double.parseDouble(parts[i]);
                }
                data.add(row);
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

        return data;
    }


    private static double calculateMean(double[] scores) {
        double sum = 0.0;
        for (double score : scores) {
            sum += score;
        }
        return sum / scores.length;
    }

    private static double calculateStandardDeviation(double[] scores, double mean) {
        double sumOfSquaredDifferences = 0.0;
        for (double score : scores) {
            sumOfSquaredDifferences += Math.pow(score - mean, 2);
        }
        return Math.sqrt(sumOfSquaredDifferences / scores.length);
    }


    private static <T extends Comparable<T>> List<Integer> findTopNIndices(ArrayList<T> list, int n, Comparator<T> comparator) {
        List<Integer> indices = IntStream.range(0, list.size()).boxed().sorted((i1, i2) -> comparator.compare(list.get(i1), list.get(i2))).collect(Collectors.toList());
        return indices.subList(0, Math.min(n, indices.size()));
    }

    private static List<Map.Entry<String, Double>> rankKeywords(List<CompWord> compData, double wSurvey, double wCompkey) {
        List<Map.Entry<String, Double>> list = new ArrayList<>();

        for (CompWord keywordComp : compData) {
            String combinedKeyword = keywordComp.getMidWord() + "-" + keywordComp.getWord();
            if (surveyScores.containsKey(keywordComp.getMidWord()) || surveyScores.containsKey(keywordComp.getWord())) {
                double surveyScore = Math.max(
                        surveyScores.getOrDefault(keywordComp.getMidWord(), 0.0),
                        surveyScores.getOrDefault(keywordComp.getWord(), 0.0)
                );
                double compScore = keywordComp.getComp();

                // 计算最终得分
                double finalScore = (wSurvey * surveyScore + wCompkey * compScore) / (wSurvey + wCompkey);
                list.add(new AbstractMap.SimpleEntry<>(combinedKeyword, DataFormatUtil.roundToFourDecimalPlaces(finalScore)));
            }
        }

        // 根据最终得分降序排序
        return list.stream()
                .sorted((o1, o2) -> Double.compare(o2.getValue(), o1.getValue()))
                .collect(Collectors.toList());
    }
}
